#!/usr/bin/env python
# -*- coding: utf-8 -*-

import unittest

from ws9 import line

class TestStrLine(unittest.TestCase):
    
    def setUp(self):
        self.string = '    Hello, World!\r\n'
        self.line = line.Line(self.string, tab_width=4)
    
    def testStr(self):
        self.assertEqual(str(self.line), self.string)
    
    def testGetEnding(self):
        self.assertEqual(self.line.ending, '\r\n')
    
    def testSetEnding(self):
        self.line.ending = '\n'
        self.assertEqual(self.line, '    Hello, World!\n')
    
    def testDelEnding(self):
        del self.line.ending
        self.assertEqual(self.line, '    Hello, World!')
    
    def testGetIndent(self):
        self.assertEqual(self.line.indent, '    ')
    
    def testSetIndent(self):
        self.line.indent = '  '
        self.assertEqual(self.line, '  Hello, World!\r\n')
    
    def testDelIndent(self):
        del self.line.indent
        self.assertEqual(self.line, 'Hello, World!\r\n')
    
    def testGetIndentType(self):
        self.assertEqual(self.line.indent_type, ' ')
    
    def testSetIndentType(self):
        self.line.indent_type = '\t'
        self.assertEqual(self.line, '\tHello, World!\r\n')
    
    def testDelIndentType(self):
        del self.line.indent_type
        self.assertEqual(self.line, '    Hello, World!\r\n')
    
    def testGetBody(self):
        self.assertEqual(self.line.body, 'Hello, World!')
    
    def testSetBody(self):
        self.line.body = 'Another String'
        self.assertEqual(self.line, '    Another String\r\n')
    
    def testDelBody(self):
        del self.line.body
        self.assertEqual(self.line, '    \r\n')
    
    def testInit(self):
        two_line_string = '  Hi there.\nThis is a second line.\n'
        two_line_line = line.Line(two_line_string)
        self.assertEqual(two_line_line, '  Hi there.\n')
    
    def testAdd(self):
        second_string = ' How are you?\n'
        modified_line = self.line + second_string
        self.assertEqual(modified_line, '    Hello, World! How are you?\r\n')
    
    def testContainsTrue(self):
        self.assert_('Hello' in self.line)
    
    def testContainsFalse(self):
        self.failIf('\r\n' in self.line)
    
    def testEqual(self):
        self.assert_(self.line == self.string)
    
    def testGreaterOrEqual(self):
        self.assert_(self.line >= 'Good Day')
        self.assert_(self.line >= 'Hello, World!')
    
    def testLessOrEqual(self):
        self.assert_(self.line <= 'Hello, World!')
        self.assert_(self.line <= 'I am bored.')
    
    def testLength(self):
        self.assertEqual(len(self.line), len(self.string))
    
    def testGreater(self):
        self.assert_(self.line > 'Good Day')
    
    def testLess(self):
        self.assert_(self.line < 'I am bored.')
    
    def testMod(self):
        fmt_line = line.Line('    The time is %2d:%2d.\r\n')
        self.assertEqual(fmt_line % (10, 30), '    The time is 10:30.\r\n')
    
    def testMultiply(self):
        self.assertEqual(self.line * 2, '    Hello, World!Hello, World!\r\n')
    
    def testNotEqual(self):
        self.assert_(self.line != 'Blah blah')
    
    def testReverseMod(self):
        self.assertEqual('MSG: %s' % self.line, 'MSG:     Hello, World!\r\n')
    
    def testReverseMultiply(self):
        self.assertEqual(2 * self.line, '    Hello, World!Hello, World!\r\n')
    
    def testCapitalize(self):
        lower_line = line.Line('    hello, world!\r\n')
        self.assertEqual(lower_line.capitalize(), '    Hello, world!\r\n')
    
    def testCenter(self):
        self.assertEqual(self.line.center(20), '       Hello, World!    \r\n')
    
    def testCount(self):
        self.assertEqual(self.line.count('l'), 3)
        self.assertEqual(self.line.count(' '), 1)
    
    def testFind(self):
        self.assertEqual(self.line.find('ll'), 6)
        self.assertEqual(self.line.find('a'), -1)
    
    def testIndex(self):
        self.assertEqual(self.line.index('ll'), 6)
        self.assertRaises(ValueError, self.line.index, 'a')
        
    def testIsAlphaNumeric(self):
        alnum_line = line.Line('    bRyUXnsQeCO1t96QO0niYDfz3mKYQs\n')
        self.assert_(alnum_line.isalnum())
        self.failIf(self.line.isalnum())
    
    def testIsAlpha(self):
        alpha_line = line.Line('\tabcdefghijklmnopqrstuvwxyz\n')
        self.assert_(alpha_line.isalpha())
        self.failIf(self.line.isalpha())
    
    def testIsDigit(self):
        digit_line = line.Line('    \t1010011010\r\n')
        self.assert_(digit_line.isdigit())
        self.failIf(self.line.isdigit())
    
    def testIsLower(self):
        lower_line = line.Line('    hello, world!\r\n')
        self.assert_(lower_line.islower())
        self.failIf(self.line.islower())
    
    def testIsUpper(self):
        upper_line = line.Line('    HELLO, WORLD!\r\n')
        self.assert_(upper_line.isupper())
        self.failIf(self.line.isupper())
    
    def testJoin(self):
        join_list = ['a', 'b']
        self.assertEqual(self.line.join(join_list), 'a    Hello, World!\r\nb')
    
    def testReverseFind(self):
        self.assertEqual(self.line.rfind('l'), 14)
        self.assertEqual(self.line.rfind('a'), -1)
    
    def testReverseIndex(self):
        self.assertEqual(self.line.rindex('l'), 14)
        self.assertRaises(ValueError, self.line.rindex, 'a')
    
    def testDecode(self):
        decoded = self.line.decode('utf-8')
        self.assert_(isinstance(decoded, line.UnicodeLine))
        self.assertEqual(decoded, self.line)
    
    def testEncode(self):
        uni_line = line.UnicodeLine(u'    ¿Qué?\n')
        self.assertEqual(unicode(uni_line), u'    \xbfQu\xe9?\n')
        encoded = uni_line.encode('utf-8')
        self.assertEqual(encoded, '    \xc2\xbfQu\xc3\xa9?\n')
        self.assert_(isinstance(encoded, line.StrLine))
    
    def testEndsWith(self):
        self.assert_(self.line.endswith('World!'))
        self.failIf(self.line.endswith('\n'))
    
    def testExpandTabs(self):
        tab_line = line.StrLine('\tHello, World!\r\n')
        self.assertEqual(tab_line.expandtabs(), self.line)
    
    def testLeftJustify(self):
        self.assertEqual(self.line.ljust(16), '    Hello, World!   \r\n')
    
    def testLower(self):
        self.assertEqual(self.line.lower(), '    hello, world!\r\n')
    
    def testLeftStrip(self):
        self.assertEqual(self.line.lstrip('H'), '    ello, World!\r\n')
        self.assertNotEqual(self.line.lstrip(' '), 'Hello, World!\r\n')
    
    def testPartition(self):
        self.assertEqual(self.line.partition('o'), ('Hell', 'o', ', World!'))
    
    def testReplace(self):
        self.assertEqual(self.line.replace('o', 'a'), '    Hella, Warld!\r\n')
        self.assert_(str(self.line.replace(' ', '')).startswith(' '))
    
    def testRightJustify(self):
        self.assertEqual(self.line.rjust(16), '   Hello, World!\r\n')
        self.assertEqual(self.line.rjust(0), 'Hello, World!\r\n')
    
    def testRightPartition(self):
        self.assertEqual(self.line.rpartition('o'), ('Hello, W', 'o', 'rld!'))
    
    def testRightSplit(self):
        self.assertEqual(self.line.rsplit('o'), ['Hell', ', W', 'rld!'])
        self.assertEqual(self.line.rsplit('o', 1), ['Hello, W', 'rld!'])
    
    def testRightStrip(self):
        self.assertEqual(self.line.rstrip('!'), '    Hello, World\r\n')
    
    def testSplit(self):
        self.assertEqual(self.line.split('o'), ['Hell', ', W', 'rld!'])
        self.assertEqual(self.line.split('o', 1), ['Hell', ', World!'])
    
    def testSplitLines(self):
        self.assertEqual(self.line.splitlines(True), [self.line])
        self.assertEqual(self.line.splitlines(False), ['    Hello, World!'])
    
    def testStartsWith(self):
        self.assert_(self.line.startswith('Hello'))
        self.failIf(self.line.startswith(' '))
    
    def testStrip(self):
        self.assertEqual(self.line.strip('H!'), '    ello, World\r\n')
    
    def testSwapCase(self):
        self.assertEqual(self.line.swapcase(), '    hELLO, wORLD!\r\n')
    
    def testTitle(self):
        self.assertEqual(self.line.title(), self.line)
        lower_line = line.StrLine('    hello, world!\r\n')
        self.assertEqual(lower_line.title(), self.line)
    
    def testTranslate(self):
        trans_table = [chr(i) for i in range(256)]
        trans_table[ord('l')] = 'A'
        trans_table[ord('\n')] = '\r'
        trans_string = ''.join(trans_table)
        translated = self.line.translate(trans_string)
        self.assertEqual(translated, '    HeAAo, WorAd!\r\n')
    
    def testUpper(self):
        self.assertEqual(self.line.upper(), '    HELLO, WORLD!\r\n')
    
    def testZeroFill(self):
        self.assertEqual(self.line.zfill(16), '    000Hello, World!\r\n')


class TestUnicodeLine(unittest.TestCase):
    
    def setUp(self):
        self.string = u'    Hello, World!\r\n'
        self.line = line.Line(self.string, tab_width=4)
    
    def testUnicode(self):
        self.assertEqual(unicode(self.line), self.string)
    
    def testTranslate(self):
        trans_table = {}
        trans_table[ord(u'l')] = ord(u'A')
        trans_table[ord(u'\n')] = ord(u'\r')
        translated = self.line.translate(trans_table)
        self.assertEqual(translated, u'    HeAAo, WorAd!\r\n')
    

class TestUnexpand(unittest.TestCase):
    
    def testNormal(self):
        string = '    '
        self.assertEqual(line.unexpand(string, tab_width=2), '\t\t')
    
    def testVaryingTabWidth(self):
        string = ' ' * 12
        for width in [2, 3, 4, 6, 12]:
            self.assertEqual(line.unexpand(string, tab_width=width),
                '\t' * (12 / width))
    
    def testShort(self):
        string = '    '
        self.assertEqual(line.unexpand(string, tab_width=8), string)
    
    def testLong(self):
        string = '    '
        self.assertEqual(line.unexpand(string, tab_width=3), '\t ')
    
    def testMixedNormalNormal(self):
        string = '    DATA  '
        self.assertEqual(line.unexpand(string, tab_width=2), '\t\tDATA\t')
    
    def testMixedNormalShort(self):
        string = '    DATA  '
        self.assertEqual(line.unexpand(string, tab_width=4), '\tDATA  ')
    
    def testMixedNormalLong(self):
        string = '  DATA   '
        self.assertEqual(line.unexpand(string, tab_width=2), '\tDATA\t ')
    
    def testMixedShortNormal(self):
        string = '  DATA    '
        self.assertEqual(line.unexpand(string, tab_width=4), '  DATA\t')
    
    def testMixedShortShort(self):
        string = '  DATA  '
        self.assertEqual(line.unexpand(string, tab_width=4), string)
    
    def testMixedShortLong(self):
        string = '  DATA    '
        self.assertEqual(line.unexpand(string, tab_width=3), '  DATA\t ')
    
    def testMixedLongNormal(self):
        string = '   DATA  '
        self.assertEqual(line.unexpand(string, tab_width=2), '\t DATA\t')
    
    def testMixedLongShort(self):
        string = '   DATA '
        self.assertEqual(line.unexpand(string, tab_width=2), '\t DATA ')
    
    def testMixedLongLong(self):
        string = '   DATA   '
        self.assertEqual(line.unexpand(string, tab_width=2), '\t DATA\t ')


class TestBreakup(unittest.TestCase):
    
    def testLengthOne(self):
        data = '    '
        self.assertEqual(line.breakup(data, seps=' '), [data])
    
    def testLengthTwo(self):
        data = '   AAA'
        self.assertEqual(line.breakup(data, seps=' '), ['   ', 'AAA'])
    
    def testLengthThree(self):
        data = '   AAA   '
        self.assertEqual(line.breakup(data, seps=' '), ['   ', 'AAA', '   '])


class TestLine(unittest.TestCase):
    
    def testMakeString(self):
        data = '\t  Hello, World!\r\n'
        self.assert_(isinstance(line.Line(data), line.StrLine))
    
    def testMakeUnicode(self):
        data = u'\tHola. ¿Qué tal?\r'
        self.assert_(isinstance(line.Line(data), line.UnicodeLine))


if __name__ == '__main__':
    unittest.main()
